/**
 * @PemTcpClientInitializer.java  COPYRIGHT xiaojian
 * 
 * Created on 2017年12月28日 下午4:00:51
 */
package xj.toolkit.netty.initializer;

import java.util.List;

import javax.net.ssl.SSLEngine;

import org.springframework.core.io.Resource;

import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslHandler;
import io.netty.handler.ssl.SslProvider;

/**
 * @author <a href="mailto:cxj2000@gmail.com">xiaojian.cao</a>
 *
 */
public abstract class PemTcpClientInitializer extends SslBaseInitializer {

	/**
	 * 客户端证书。
	 */
	private Resource keyCertResource = null;

	/**
	 * 客户端私钥
	 */
	private Resource privateKeyResource = null;

	private List<ChannelHandler> otherHandlers = Lists.newArrayList();

	public Resource getKeyCertResource() {
		return keyCertResource;
	}

	public void setKeyCertResource(Resource keyCertResource) {
		this.keyCertResource = keyCertResource;
	}

	public Resource getPrivateKeyResource() {
		return privateKeyResource;
	}

	public void setPrivateKeyResource(Resource privateKeyResource) {
		this.privateKeyResource = privateKeyResource;
	}

	@Override
	protected void addCodecHandler(ChannelPipeline pipeline) throws Exception {
		pipeline.addLast("tcpRequestEncoder", getTcpRequestEncoder()).addLast("tcpResponseDecoder",
				getTcpResponseDecoder());
	}

	@Override
	protected void addBusinessHandler(ChannelPipeline pipeline) throws Exception {
		if (otherHandlers == null || otherHandlers.size() == 0) {
			return;
		}

		for (ChannelHandler handler : otherHandlers) {
			pipeline.addLast(handler.toString(), handler);
		}
	}

	@Override
	public void initChannel(Channel ch) throws Exception {
		if (isUseSsl()) {

			if (privateKeyResource == null || !privateKeyResource.exists()) {
				throw new Exception("Pls set privateKey file.");
			}

			if (keyCertResource == null || !keyCertResource.exists()) {
				throw new Exception("Pls set keycertificate file.");
			}

			SslContext sslContext = SslContextBuilder.forClient()
					.keyManager(keyCertResource.getInputStream(), privateKeyResource.getInputStream())
					.sslProvider(SslProvider.JDK).build();

			SSLEngine engine = sslContext.newEngine(ch.alloc());
			engine.setUseClientMode(true);
			ch.pipeline().addFirst("ssl", new SslHandler(engine));
		}

		super.initChannel(ch);
	}

	public abstract ChannelHandler getTcpResponseDecoder();

	public abstract ChannelHandler getTcpRequestEncoder();

	public void addOtherHandler(ChannelHandler otherHandler) {
		Preconditions.checkArgument(otherHandler != null);
		otherHandlers.add(otherHandler);
	}
}
